using RAG.Application.Interfaces;
using RAG.Application.Dtos;
using RAG.Application.Commands;
using RAG.Domain.Interfaces;
using RAG.Domain.Entities.App;
using RAG.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;

namespace RAG.Application.Services;

/// <summary>
/// 权限服务实现
/// </summary>
public class AppPermissionService : IAppPermissionService
{
    private readonly RagDbContext _db;
    private readonly IDomainEventPublisher _eventPublisher;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public AppPermissionService(
        RagDbContext db,
        IDomainEventPublisher eventPublisher,
        IHttpContextAccessor httpContextAccessor)
    {
        _db = db;
        _eventPublisher = eventPublisher;
        _httpContextAccessor = httpContextAccessor;
    }

    /// <summary>
    /// 获取当前用户权限
    /// </summary>
    public async Task<ApiResult> GetCurrentUserPermissionsAsync()
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
                return ApiResult.Failed((int)ApiStatusCode.UNAUTHORIZED, "用户未登录");

            var user = await _db.Users
                .Include(u => u.Roles)
                .ThenInclude(r => r.Permissions)
                .Where(u => !u.IsDeleted && u.IsActive)
                .FirstOrDefaultAsync(u => u.Id == userId);

            if (user == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");

            var permissions = user.Roles
                .Where(r => !r.IsDeleted && r.IsActive)
                .SelectMany(r => r.Permissions)
                .Where(p => !p.IsDeleted && p.IsActive)
                .Select(p => new PermissionDto
                {
                    Id = p.Id,
                    PermissionCode = p.PermissionCode,
                    PermissionName = p.PermissionName,
                    PermissionDescription = p.PermissionDescription
                })
                .DistinctBy(p => p.Id)
                .OrderBy(p => p.PermissionCode)
                .ToList();

            var result = new
            {
                UserId = user.Id,
                Username = user.Username,
                Permissions = permissions,
                PermissionCount = permissions.Count
            };

            return ApiResult.Success("获取用户权限成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取用户权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取权限列表（分页）
    /// </summary>
    public async Task<ApiResult> GetPermissionsAsync(int page, int size, string? search = null)
    {
        try
        {
            var query = _db.Permissions
                .Include(p => p.Roles)
                .Where(p => !p.IsDeleted)
                .AsQueryable();

            // 定义搜索条件 - 支持权限代码、名称和描述搜索
            Func<IQueryable<Permission>, string, IQueryable<Permission>> searchPredicate = (q, term) =>
                q.Where(p => 
                    p.PermissionCode.Contains(term) || 
                    p.PermissionName.Contains(term) || 
                    (p.PermissionDescription != null && p.PermissionDescription.Contains(term)));

            // 定义排序条件 - 使用稳定的排序方式，避免启用禁用后上下跳动
            Func<IQueryable<Permission>, IQueryable<Permission>> orderBy = q => 
                q.OrderBy(p => p.PermissionCode).ThenBy(p => p.Id);

            // 使用分页工具
            var pagedResult = await query.ToPagedResultAsync(
                page, 
                size, 
                searchPredicate, 
                search, 
                orderBy);

            // 转换为DTO
            var permissionDtos = pagedResult.Items.Select(p => new PermissionDetailDto
            {
                Id = p.Id,
                PermissionCode = p.PermissionCode,
                PermissionName = p.PermissionName,
                PermissionDescription = p.PermissionDescription,
                CreatedAt = p.CreatedAt,
                UpdatedAt = p.UpdatedAt,
                IsActive = p.IsActive,
                RoleCount = p.Roles.Count
            }).ToList();

            // 创建最终结果
            var result = new
            {
                Permissions = permissionDtos,
                Total = pagedResult.Total,
                Page = pagedResult.Page,
                Size = pagedResult.Size,
                TotalPages = pagedResult.TotalPages,
                HasPreviousPage = pagedResult.HasPreviousPage,
                HasNextPage = pagedResult.HasNextPage
            };

            return ApiResult.Success("获取权限列表成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取权限列表时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 根据ID获取权限详情
    /// </summary>
    public async Task<ApiResult> GetPermissionByIdAsync(Guid permissionId)
    {
        try
        {
            var permission = await _db.Permissions
                .Include(p => p.Roles)
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.Id == permissionId);

            if (permission == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");

            var permissionDto = new PermissionDetailDto
            {
                Id = permission.Id,
                PermissionCode = permission.PermissionCode,
                PermissionName = permission.PermissionName,
                PermissionDescription = permission.PermissionDescription,
                CreatedAt = permission.CreatedAt,
                UpdatedAt = permission.UpdatedAt,
                IsActive = permission.IsActive,
                RoleCount = permission.Roles.Count
            };

            return ApiResult.Success("获取权限详情成功", permissionDto);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取权限详情时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 创建权限
    /// </summary>
    public async Task<ApiResult> CreatePermissionAsync(CreatePermissionDto dto)
    {
        try
        {
            // 验证输入
            if (string.IsNullOrWhiteSpace(dto.PermissionName))
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限名称不能为空");

            if (string.IsNullOrWhiteSpace(dto.PermissionCode))
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限代码不能为空");

            // 检查权限代码是否已存在
            var existingPermission = await _db.Permissions
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.PermissionCode == dto.PermissionCode);

            if (existingPermission != null)
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限代码已存在");

            var permission = new Permission
            {
                Id = Guid.NewGuid(),
                PermissionCode = dto.PermissionCode,
                PermissionName = dto.PermissionName,
                PermissionDescription = dto.PermissionDescription,
                IsActive = true,
                IsDeleted = false,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            _db.Permissions.Add(permission);
            await _db.SaveChangesAsync();

            return ApiResult.Success("权限创建成功", new { Id = permission.Id });
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"创建权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 更新权限
    /// </summary>
    public async Task<ApiResult> UpdatePermissionAsync(Guid permissionId, UpdatePermissionDto dto)
    {
        try
        {
            // 验证输入
            if (string.IsNullOrWhiteSpace(dto.PermissionName))
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限名称不能为空");

            if (string.IsNullOrWhiteSpace(dto.PermissionCode))
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限代码不能为空");

            var permission = await _db.Permissions
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.Id == permissionId);

            if (permission == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");

            // 检查权限代码是否已被其他权限使用
            var existingPermission = await _db.Permissions
                .Where(p => !p.IsDeleted && p.Id != permissionId)
                .FirstOrDefaultAsync(p => p.PermissionCode == dto.PermissionCode);

            if (existingPermission != null)
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限代码已被其他权限使用");

            permission.PermissionCode = dto.PermissionCode;
            permission.PermissionName = dto.PermissionName;
            permission.PermissionDescription = dto.PermissionDescription;
            permission.UpdatedAt = DateTime.UtcNow;

            await _db.SaveChangesAsync();

            return ApiResult.Success("权限更新成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"更新权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 删除权限（软删除）
    /// </summary>
    public async Task<ApiResult> DeletePermissionAsync(Guid permissionId)
    {
        try
        {
            var permission = await _db.Permissions
                .Include(p => p.Roles)
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.Id == permissionId);

            if (permission == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");

            // 检查是否有角色使用此权限
            if (permission.Roles.Any())
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "该权限下还有角色，无法删除");

            // 软删除
            permission.IsDeleted = true;
            permission.UpdatedAt = DateTime.UtcNow;
            await _db.SaveChangesAsync();

            return ApiResult.Success("权限删除成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"删除权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 启用权限
    /// </summary>
    public async Task<ApiResult> EnablePermissionAsync(Guid permissionId)
    {
        try
        {
            var permission = await _db.Permissions
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.Id == permissionId);

            if (permission == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");

            if (permission.IsActive)
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限已经是启用状态");

            permission.IsActive = true;
            permission.UpdatedAt = DateTime.UtcNow;
            await _db.SaveChangesAsync();

            return ApiResult.Success("权限启用成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"启用权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 禁用权限
    /// </summary>
    public async Task<ApiResult> DisablePermissionAsync(Guid permissionId)
    {
        try
        {
            var permission = await _db.Permissions
                .Where(p => !p.IsDeleted)
                .FirstOrDefaultAsync(p => p.Id == permissionId);

            if (permission == null)
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");

            if (!permission.IsActive)
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "权限已经是禁用状态");

            permission.IsActive = false;
            permission.UpdatedAt = DateTime.UtcNow;
            await _db.SaveChangesAsync();

            return ApiResult.Success("权限禁用成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"禁用权限时发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取当前用户ID
    /// </summary>
    private Guid GetCurrentUserId()
    {
        var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier);
        return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) ? userId : Guid.Empty;
    }
} 